package com.xsir.config;

import com.xsir.jwt.JwtFilter;
import com.xsir.jwt.JwtRealm;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;


/**
 * shiro配置类
 *
 * @author user
 */
@Configuration
@Slf4j
public class ShiroConfig {
    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager") SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        
        Map<String, Filter> filterMap = new HashMap<>();
        // 设置自定义的jwtFilter
        filterMap.put("jwtFilter", new JwtFilter());
        shiroFilterFactoryBean.setFilters(filterMap);
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 设置所有请求经过JwtFilter
        Map<String, String> filterUrlMap = new HashMap<>();
        filterUrlMap.put("/**", "jwtFilter");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterUrlMap);
        return shiroFilterFactoryBean;
    }
    
    /**
     * 注入 securityManager (org.apache.jwt.mgt.SecurityManager)
     *
     * 【注意：容器中自动配置了SecurityManager  所以使用SessionSecurityManager覆盖】
     * @return SessionSecurityManager
     */
    @Bean(name = "securityManager")
    public SessionsSecurityManager securityManager(@Qualifier("jwtRealm") Realm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(realm);
        return securityManager;
    }
    
    /**
     * 自定义身份认证 realm;
     * <p>
     * 必须写这个类，并加上 @Bean 注解，目的是注入 JwtRealm，
     * 否则会影响 JwtRealm类 中其他类的依赖注入
     */
    @Bean(name = "jwtRealm")
    public JwtRealm jwtRealm() {
        return new JwtRealm();
    }
    
    /**
     * 配置shiro的生命周期
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
    
    /**
     * 开启shiro aop注解支持，不开启的话权限验证就会失效
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor sourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        sourceAdvisor.setSecurityManager(securityManager);
        return sourceAdvisor;
    }
    
    // /**
    //  * 配置异常处理，不配置的话没有权限后台报错，前台不会跳转到403页面
    //  */
    // @Bean(name="simpleMappingExceptionResolver")
    // public SimpleMappingExceptionResolver
    // createSimpleMappingExceptionResolver() {
    //     SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
    //     Properties mappings = new Properties();
    //     // 数据库异常处理
    //     mappings.setProperty("DatabaseException", "databaseError");
    //     mappings.setProperty("UnauthorizedException","403");
    //     simpleMappingExceptionResolver.setExceptionMappings(mappings);
    //     simpleMappingExceptionResolver.setDefaultErrorView("error");
    //     simpleMappingExceptionResolver.setExceptionAttribute("ex");
    //     return simpleMappingExceptionResolver;
    // }
}